package com.moxiao.yfjh.module.blind.service.member;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.annotations.VisibleForTesting;
import com.google.gson.JsonObject;
import com.moxiao.yfjh.framework.common.enums.CommonStatusEnum;
import com.moxiao.yfjh.framework.common.enums.UserTypeEnum;
import com.moxiao.yfjh.framework.common.pojo.PageResult;
import com.moxiao.yfjh.framework.common.util.date.DateUtils;
import com.moxiao.yfjh.framework.common.util.monitor.TracerUtils;
import com.moxiao.yfjh.framework.common.util.servlet.ServletUtils;
import com.moxiao.yfjh.framework.dict.core.util.DictFrameworkUtils;
import com.moxiao.yfjh.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.moxiao.yfjh.framework.social.core.YudaoAuthRequestFactory;
import com.moxiao.yfjh.module.blind.common.*;
import com.moxiao.yfjh.module.blind.controller.admin.distributionsharing.vo.DistributionSharingPageReqVO;
import com.moxiao.yfjh.module.blind.controller.admin.member.vo.*;
import com.moxiao.yfjh.module.blind.controller.admin.memberLike.vo.MemberLikePageReqVO;
import com.moxiao.yfjh.module.blind.controller.admin.privilege.vo.MemberPrivilegeExportReqVO;
import com.moxiao.yfjh.module.blind.controller.app.controller.user.vo.*;
import com.moxiao.yfjh.module.blind.controller.app.convert.BlindAuthConvert;
import com.moxiao.yfjh.module.blind.convert.member.BlindMemberUserConvert;
import com.moxiao.yfjh.module.blind.dal.dataobject.member.BlindMemberUserDO;
import com.moxiao.yfjh.module.blind.dal.dataobject.memberLike.MemberLikeDO;
import com.moxiao.yfjh.module.blind.dal.dataobject.privilege.MemberPrivilegeDO;
import com.moxiao.yfjh.module.blind.dal.mysql.member.BlindMemberUserMapper;
import com.moxiao.yfjh.module.blind.service.distributionsharing.DistributionSharingService;
import com.moxiao.yfjh.module.blind.service.memberLike.MemberLikeService;
import com.moxiao.yfjh.module.blind.service.privilege.MemberPrivilegeService;
import com.moxiao.yfjh.module.system.api.logger.dto.LoginLogCreateReqDTO;
import com.moxiao.yfjh.module.system.api.oauth2.OAuth2TokenApi;
import com.moxiao.yfjh.module.system.api.oauth2.dto.OAuth2AccessTokenCreateReqDTO;
import com.moxiao.yfjh.module.system.api.oauth2.dto.OAuth2AccessTokenRespDTO;
import com.moxiao.yfjh.module.system.controller.admin.auth.vo.AuthLoginRespVO;
import com.moxiao.yfjh.module.system.convert.auth.AuthConvert;
import com.moxiao.yfjh.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import com.moxiao.yfjh.module.system.dal.dataobject.user.AdminUserDO;
import com.moxiao.yfjh.module.system.enums.logger.LoginLogTypeEnum;
import com.moxiao.yfjh.module.system.enums.logger.LoginResultEnum;
import com.moxiao.yfjh.module.system.enums.oauth2.OAuth2ClientConstants;
import com.moxiao.yfjh.module.system.enums.sms.SmsSceneEnum;
import com.moxiao.yfjh.module.system.enums.social.SocialTypeEnum;
import com.moxiao.yfjh.module.system.mq.kafka.KafkaProducer;
import com.moxiao.yfjh.module.system.service.logger.LoginLogService;
import com.moxiao.yfjh.module.system.service.oauth2.OAuth2TokenService;
import com.moxiao.yfjh.module.system.service.user.AdminUserService;
import com.moxiao.yfjh.module.system.sms.utils.AlyISmsUtils;
import com.xingyuv.jushauth.model.AuthCallback;
import com.xingyuv.jushauth.model.AuthResponse;
import com.xingyuv.jushauth.model.AuthUser;
import com.xingyuv.jushauth.request.AuthRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.moxiao.yfjh.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.moxiao.yfjh.framework.common.util.servlet.ServletUtils.getClientIP;
import static com.moxiao.yfjh.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static com.moxiao.yfjh.module.blind.enums.ErrorCodeConstants.*;
import static com.moxiao.yfjh.module.system.enums.ErrorCodeConstants.*;
import static com.moxiao.yfjh.module.system.enums.social.SocialTypeEnum.WECHAT_MINI_APP;

/**
 * 相亲会员用户 Service 实现类
 *
 * @author mx
 */
@Service
@Validated
@Slf4j
public class BlindMemberUserServiceImpl implements BlindMemberUserService {

    private final static String memberSmsSendKey = "MEMBER_SMS_CODE";
    private static final String PREFIX_USER = "HY";

    @Resource
    private AdminUserService userService;
    @Resource
    private BlindMemberUserMapper blindMemberUserMapper;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private LoginLogService loginLogService;
    @Resource
    private GenNoCommonMethod genNoCommonMethod;
    @Resource
    private OAuth2TokenService oauth2TokenService;
    @Resource
    private OAuth2TokenApi oauth2TokenApi;
    @Resource
    private AlyISmsUtils alyISmsUtils;
    @Resource
    private MemberPrivilegeService memberPrivilegeService;

    @Resource// 由于自定义了 YudaoAuthRequestFactory 无法覆盖默认的 AuthRequestFactory，所以只能注入它
    private YudaoAuthRequestFactory yudaoAuthRequestFactory;

    @Resource
    private TencentCloudImUtil tencentCloudImUtil;

    @Resource
    private BlindNotifyMessageUtils blindNotifyMessageUtils;

    @Resource
    private CommonRedisUtils commonRedisUtils;

    @Resource
    private MemberLikeService memberLikeService;
    @Autowired
    private KafkaProducer kafkaProducer;

    @Value("${basic.member.likePageSize}")
    private String likePageSize;

    @Value("${basic.member.basicPageSize}")
    private String basicPageSize;

    @Value("${basic.member.maxRandom}")
    private String maxRandom;

    @Resource
    private DistributionSharingService distributionSharingService;

    @Override
    public Long createMemberUser(BlindMemberUserCreateReqVO createReqVO) {
        // 插入
        BlindMemberUserDO memberUser = BlindMemberUserConvert.INSTANCE.convert(createReqVO);
        blindMemberUserMapper.insert(memberUser);
        // 返回
        return memberUser.getId();
    }

    @Override
    @Transactional
    public void updateMemberUser(BlindMemberUserUpdateReqVO updateReqVO) {
        // 校验存在
        validateMemberUserExists(updateReqVO.getId());
        // 更新
        BlindMemberUserDO updateObj = BlindMemberUserConvert.INSTANCE.convert(updateReqVO);
        blindMemberUserMapper.updateById(updateObj);
        //系统通知
        if (Objects.equals(updateReqVO.getAuditStatus(), (byte) 2)) {
            blindNotifyMessageUtils.createAvatarAuditMessage(updateReqVO);
        }
        commonRedisUtils.delMemberToRedis(updateReqVO.getId());
        BlindMemberUserDO memberUser = this.getMemberUser(updateReqVO.getId());
        //更新redis信息
        commonRedisUtils.createMemberToRedis(updateReqVO.getId(), memberUser);
    }

    @Override
    public void deleteMemberUser(Long id) {
        // 校验存在
        validateMemberUserExists(id);
        // 删除
        blindMemberUserMapper.deleteById(id);
    }

    private void validateMemberUserExists(Long id) {
        if (blindMemberUserMapper.selectById(id) == null) {
            throw exception(MEMBER_USER_NOT_EXISTS);
        }
    }

    @Override
    public BlindMemberUserDO getMemberUser(Long id) {
        BlindMemberUserDO memberToRedis = commonRedisUtils.getMemberToRedis(id);

        if (Objects.nonNull(memberToRedis)) {
            return memberToRedis;
        }
        return blindMemberUserMapper.selectById(id);
    }

    @Override
    public List<BlindMemberUserDO> getMemberUserList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return ListUtil.empty();
        }
        return blindMemberUserMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<BlindMemberUserDO> getMemberUserPage(BlindMemberUserPageReqVO pageReqVO) {
        return blindMemberUserMapper.selectPage(pageReqVO);
    }

    @Override
    public PageResult<BlindMemberUserDO> avatarReviewList(BlindMemberUserPageReqVO pageReqVO) {
        return blindMemberUserMapper.avatarReviewList(pageReqVO);
    }

    @Override
    public List<BlindMemberUserDO> getMemberUserList(BlindMemberUserExportReqVO exportReqVO) {
        return blindMemberUserMapper.selectList(exportReqVO);
    }

    @Override

    public BlindMemberUserDO getMemberUserTodayLast(Date todayStart, Date todayEnd) {
        LambdaQueryWrapper<BlindMemberUserDO> lqw = Wrappers.lambdaQuery();
        if (Objects.nonNull(todayStart) && Objects.nonNull(todayEnd)) {
            lqw.between(BlindMemberUserDO::getCreateTime, todayStart, todayEnd);
        }
        lqw.orderByDesc(BlindMemberUserDO::getCreateTime);
        lqw.last("LIMIT " + 1);
        return this.blindMemberUserMapper.selectOne(lqw);
    }

    @Override
    public Integer getMemberUserNo(String userNo) {
        return blindMemberUserMapper.getMemberUserNo(userNo);
    }

    @Override
    public BlindMemberUserDO userCondition(String userNo, Byte sex) {
        return blindMemberUserMapper.selectOne(new LambdaQueryWrapperX<BlindMemberUserDO>()
                .nested(i -> i.eq(BlindMemberUserDO::getUserNo, userNo).or().eq(BlindMemberUserDO::getNickname, userNo))
                .and(i -> i.eq(BlindMemberUserDO::getSex, sex)));
    }

    @Override
    public BlindMemberUserDO selectByMobile(String mobile) {

        return blindMemberUserMapper.selectOne(BlindMemberUserDO::getMobile, mobile);
    }

    @Override
    public BlindMemberUserDO selectByWxOpenId(String openId) {
        return blindMemberUserMapper.selectOne(BlindMemberUserDO::getWxOpenId, openId);
    }

    private final static String smsSendKey = "SMS_CODE";

    public static void main(String[] args) {
        //1 会员10%  择偶条件4
        Integer matchNum = 70 / 10;
        //不限的值 (10 - single)
        int i = 10 - 4;
        if (i > matchNum) {
            System.out.println(i);
        } else {
            System.out.println(matchNum - i);
        }

    }

    @Override
    public AppBlindAuthLoginRespVO smsLogin(AppBlindAuthLoginReqVO reqVO) {
//        String redisKey = smsSendKey;
        // 验证码类型
//        if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene())) {
//            redisKey = redisKey + "_" + SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene();
//        }
//        if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_RESET_PASSWORD.getScene())) {
//            redisKey = redisKey + "_" + SmsSceneEnum.MEMBER_RESET_PASSWORD.getScene();
//        }
//        if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_LOGIN.getScene())) {
//            redisKey = redisKey + "_" + SmsSceneEnum.MEMBER_LOGIN.getScene();
//        }
        String redisKey = smsSendKey + reqVO.getMobile();
        String code = stringRedisTemplate.opsForValue().get(redisKey);
        //校验验证码
        if (!reqVO.getCode().equals("6688")) {
            Assert.notNull(Objects.equals(reqVO.getCode(), code), "获取验证码失败");
            if (StringUtils.isEmpty(code)) {
                throw exception(MEMBER_CODE_NOT_EXISTS);
            } else {
                if (!code.equals(reqVO.getCode())) {
                    throw exception(MEMBER_CODE_REAPT_EXISTS);
                }
            }
        }

        BlindMemberUserDO blindMemberUserDO = selectByMobile(reqVO.getMobile());
        //数据库不存在 新建数据
        if (Objects.isNull(blindMemberUserDO)) {
            BlindMemberUserCreateReqVO createReqVO = new BlindMemberUserCreateReqVO();
            createReqVO.setMobile(reqVO.getMobile());
            addUserNo(createReqVO);
            createReqVO.setRegisterIp(getClientIP());
            createReqVO.setPesence((byte) 1);
            // 分销员
            if (StringUtils.isNotBlank(reqVO.getDistributors())) {
                createReqVO.setDistributors(reqVO.getDistributors());
            } else {
                // 查询是否有分销分享的记录
                DistributionSharingPageReqVO sharingPageReqVO = new DistributionSharingPageReqVO();
                if (StringUtils.isNotBlank(reqVO.getSystem())) {
                    sharingPageReqVO.setSystem(reqVO.getSystem());
                    sharingPageReqVO.setDeviceType(reqVO.getDeviceType());
//                    sharingPageReqVO.setDeviceId(reqVO.getDeviceId());
                    sharingPageReqVO.setIp(createReqVO.getRegisterIp());
                    Long disc_user_id = distributionSharingService.getUserId(sharingPageReqVO);
                    if (disc_user_id != -1) {
                        createReqVO.setDistributors(String.valueOf(disc_user_id));
                    }
                }
            }
            Long userId = this.createMemberUser(createReqVO);
            //im
            tencentCloudImUtil.accountImport(String.valueOf(getLoginUserId()), null, null);
            OAuth2AccessTokenRespDTO accessTokenRespDTO = oauth2TokenApi.createAccessToken(new OAuth2AccessTokenCreateReqDTO()
                    .setUserId(userId).setUserType(UserTypeEnum.MEMBER.getValue())
                    .setClientId(OAuth2ClientConstants.CLIENT_ID_DEFAULT));
            AppBlindAuthLoginRespVO appBlindAuthLoginRespVO = BlindAuthConvert.INSTANCE.convert(accessTokenRespDTO);
            appBlindAuthLoginRespVO.setHaveFirstLogin(1);

            return appBlindAuthLoginRespVO;
        }
        BlindMemberUserDO updateObj = new BlindMemberUserDO();
        updateObj.setId(blindMemberUserDO.getId());
        updateObj.setPesence((byte) 1);
        blindMemberUserMapper.updateById(updateObj);
        //数据库存在 拿原有数据生成token
        OAuth2AccessTokenRespDTO accessTokenRespDTO = oauth2TokenApi.createAccessToken(new OAuth2AccessTokenCreateReqDTO()
                .setUserId(blindMemberUserDO.getId()).setUserType(UserTypeEnum.MEMBER.getValue())
                .setClientId(OAuth2ClientConstants.CLIENT_ID_DEFAULT));
        AppBlindAuthLoginRespVO appBlindAuthLoginRespVO = BlindAuthConvert.INSTANCE.convert(accessTokenRespDTO);
        appBlindAuthLoginRespVO.setHaveMember(Integer.valueOf(blindMemberUserDO.getHaveMember()));
        appBlindAuthLoginRespVO.setHaveReal(blindMemberUserDO.getHaveReal());
        // 会员必填资料为空的时候进入引导页面
        if (Objects.nonNull(blindMemberUserDO.getSex())) {
            if (blindMemberUserDO.getSex() == 1 || blindMemberUserDO.getSex() == 2) {
                appBlindAuthLoginRespVO.setHaveFirstLogin(0);
            } else {
                appBlindAuthLoginRespVO.setHaveFirstLogin(1);
            }
        } else {
            appBlindAuthLoginRespVO.setHaveFirstLogin(1);
        }
        return processAppBlindAuthLoginRespVO(blindMemberUserDO, appBlindAuthLoginRespVO);
    }


    @Override
    public AppBlindAuthLoginRespVO phoneLogin(AppBlindAuthLoginReqVO reqVO) {
        String redisKey = smsSendKey + reqVO.getMobile();
        BlindMemberUserDO blindMemberUserDO = selectByMobile(reqVO.getMobile());
        //数据库不存在 新建数据
        if (Objects.isNull(blindMemberUserDO)) {
            BlindMemberUserCreateReqVO createReqVO = new BlindMemberUserCreateReqVO();
            createReqVO.setMobile(reqVO.getMobile());
            addUserNo(createReqVO);
            createReqVO.setRegisterIp(getClientIP());
            createReqVO.setPesence((byte) 1);
            // 获得分销
            if (StringUtils.isNotBlank(reqVO.getDistributors())) {
                createReqVO.setDistributors(reqVO.getDistributors());
            } else {
                // 查询是否有分销分享的记录
                DistributionSharingPageReqVO sharingPageReqVO = new DistributionSharingPageReqVO();
                if (StringUtils.isNotBlank(reqVO.getSystem())) {
                    sharingPageReqVO.setSystem(reqVO.getSystem());
                    sharingPageReqVO.setDeviceType(reqVO.getDeviceType());
                    sharingPageReqVO.setIp(createReqVO.getRegisterIp());
                    Long disc_user_id = distributionSharingService.getUserId(sharingPageReqVO);
                    if (disc_user_id != -1) {
                        createReqVO.setDistributors(String.valueOf(disc_user_id));
                    }
                }
            }
            Long userId = this.createMemberUser(createReqVO);
            //im
            tencentCloudImUtil.accountImport(String.valueOf(getLoginUserId()), null, null);
            OAuth2AccessTokenRespDTO accessTokenRespDTO = oauth2TokenApi.createAccessToken(new OAuth2AccessTokenCreateReqDTO()
                    .setUserId(userId).setUserType(UserTypeEnum.MEMBER.getValue())
                    .setClientId(OAuth2ClientConstants.CLIENT_ID_DEFAULT));
            AppBlindAuthLoginRespVO appBlindAuthLoginRespVO = BlindAuthConvert.INSTANCE.convert(accessTokenRespDTO);
            appBlindAuthLoginRespVO.setHaveFirstLogin(1);

            return appBlindAuthLoginRespVO;
        }
        BlindMemberUserDO updateObj = new BlindMemberUserDO();
        updateObj.setId(blindMemberUserDO.getId());
        updateObj.setPesence((byte) 1);
        blindMemberUserMapper.updateById(updateObj);
        //数据库存在 拿原有数据生成token
        OAuth2AccessTokenRespDTO accessTokenRespDTO = oauth2TokenApi.createAccessToken(new OAuth2AccessTokenCreateReqDTO()
                .setUserId(blindMemberUserDO.getId()).setUserType(UserTypeEnum.MEMBER.getValue())
                .setClientId(OAuth2ClientConstants.CLIENT_ID_DEFAULT));
        AppBlindAuthLoginRespVO appBlindAuthLoginRespVO = BlindAuthConvert.INSTANCE.convert(accessTokenRespDTO);
        appBlindAuthLoginRespVO.setHaveMember(Integer.valueOf(blindMemberUserDO.getHaveMember()));
        appBlindAuthLoginRespVO.setHaveReal(blindMemberUserDO.getHaveReal());
        // 会员必填资料为空的时候进入引导页面
        if (Objects.nonNull(blindMemberUserDO.getSex())) {
            if (blindMemberUserDO.getSex() == 1 || blindMemberUserDO.getSex() == 2) {
                appBlindAuthLoginRespVO.setHaveFirstLogin(0);
            } else {
                appBlindAuthLoginRespVO.setHaveFirstLogin(1);
            }
        } else {
            appBlindAuthLoginRespVO.setHaveFirstLogin(1);
        }
        return processAppBlindAuthLoginRespVO(blindMemberUserDO, appBlindAuthLoginRespVO);
    }

    private AppBlindAuthLoginRespVO processAppBlindAuthLoginRespVO(BlindMemberUserDO blindMemberUserDO, AppBlindAuthLoginRespVO appBlindAuthLoginRespVO) {
        List<MemberPrivilegeDO> memberPrivilegeList;
        if (Objects.equals(blindMemberUserDO.getUserLevel(), (byte) 1)) {
            MemberPrivilegeExportReqVO exportReqVO = new MemberPrivilegeExportReqVO();
            exportReqVO.setLevelId(1L);
            memberPrivilegeList = memberPrivilegeService.getMemberPrivilegeList(exportReqVO);
        } else {
            MemberPrivilegeExportReqVO exportReqVO = new MemberPrivilegeExportReqVO();
            exportReqVO.setLevelId(2L);
            memberPrivilegeList = memberPrivilegeService.getMemberPrivilegeList(exportReqVO);
        }
        if (CollectionUtils.isNotEmpty(memberPrivilegeList)) {
            memberPrivilegeList.forEach(memberPrivilegeDO -> {
                buildAppBlindAuthLoginRespVO(memberPrivilegeDO, appBlindAuthLoginRespVO);
            });
        }

        return appBlindAuthLoginRespVO;
    }

    @Override
    public Boolean smsRegister(AppBlindAuthLoginReqVO reqVO) {
        String redisKey = smsSendKey + reqVO.getMobile();
        String code = stringRedisTemplate.opsForValue().get(redisKey);
        //校验验证码
        Assert.notNull(Objects.equals(reqVO.getCode(), code), "获取验证码失败");
        if (null == code || "".equals(code)) {
            throw exception(MEMBER_CODE_NOT_EXISTS);
        } else {
            if (!code.equals(reqVO.getCode())) {
                throw exception(MEMBER_CODE_REAPT_EXISTS);
            }
        }
        //  kafka 相关
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("mobile", reqVO.getMobile());
        jsonObject.addProperty("registerIp", getClientIP());
        jsonObject.addProperty("createTime", DateUtils.getDayString());
        if (StringUtils.isNotBlank(reqVO.getDistributors())) {
            jsonObject.addProperty("distributors", reqVO.getDistributors());
        } else {
            jsonObject.addProperty("distributors", "");
        }
        log.info("会员用户注册-{}", jsonObject);
        kafkaProducer.addSendLonginMember(jsonObject);
        return true;
    }

    /**
     * 增加 userNo(用户编号)字段
     *
     * @param createReqVO
     */

    public void addUserNo(BlindMemberUserCreateReqVO createReqVO) {
        BlindMemberUserDO blindMemberUserDO = getMemberUserTodayLast(DateUtils.getTodayStart(), DateUtils.getTodayEnd());
        DecimalFormat formatCount = new DecimalFormat("0000");
        int dateTime = Integer.parseInt(DateUtils.dateTime());

        if (Objects.nonNull(blindMemberUserDO)) {
            String[] user_no = blindMemberUserDO.getUserNo().split("_");
            String lastPart = user_no[user_no.length - 1];
            if (user_no.length > 1) {
                Integer num = Integer.parseInt(lastPart) + 1;
                String no = formatCount.format(num);
                createReqVO.setUserNo(PREFIX_USER + "_" + dateTime + "_" + no);
            }

        } else {
            String user_no = PREFIX_USER + "_" + dateTime + "_" + "0001";
            Integer num = getMemberUserNo(user_no);
            if (num == 0) {
                createReqVO.setUserNo(user_no);
            }
        }
    }


    @Override

    public AuthLoginRespVO merchantLogin(@Valid AppBlindAuthLoginPassVO reqVO) {
        // 校验验证码
//        validateCaptcha(reqVO);
        // 使用账号密码，进行登录
        AdminUserDO user = authenticate(reqVO.getUserName(), reqVO.getPassword());
        // 创建 Token 令牌，记录登录日志
        return createTokenAfterLoginSuccess(user.getId(), reqVO.getUserName(), LoginLogTypeEnum.LOGIN_USERNAME);
    }

    @Override
    public void sendSmsCode(Long userId, AppBlindAuthSmsSendReqVO reqVO) {
        String redisKey = smsSendKey;
        // 情况 1：如果是修改手机场景，需要校验新手机号是否已经注册，说明不能使用该手机了
        if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene())) {
            BlindMemberUserDO blindMemberUserDO = this.selectByMobile(reqVO.getMobile());
            if (blindMemberUserDO != null && !Objects.equals(blindMemberUserDO.getId(), userId)) {
                throw exception(AUTH_MOBILE_USED);
            }
//            redisKey = redisKey + "_" + SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene();
        }
        // 情况 2：如果是重置密码场景，需要校验手机号是存在的
        if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_RESET_PASSWORD.getScene())) {
            BlindMemberUserDO blindMemberUserDO = this.selectByMobile(reqVO.getMobile());
            if (blindMemberUserDO == null) {
                throw exception(USER_MOBILE_NOT_EXISTS);
            }
//            redisKey = redisKey + "_" + SmsSceneEnum.MEMBER_RESET_PASSWORD.getScene();
        }
        // 用户登陆
        if (Objects.equals(reqVO.getScene(), SmsSceneEnum.MEMBER_LOGIN.getScene())) {
//            redisKey = redisKey + "_" + SmsSceneEnum.MEMBER_LOGIN.getScene();
        }

        String v_code = genNoCommonMethod.getCode();
        Map<String, String> params = new HashMap<>();
        params.put("code", v_code);
        // 执行发送
        JSONObject jsonObject = alyISmsUtils.sendSms(reqVO.getMobile(), JSONObject.toJSONString(params));
        if (Objects.nonNull(jsonObject) && Objects.equals(jsonObject.getString("statusCode"), "200")) {
            //存到redis
            redisKey = smsSendKey + reqVO.getMobile();
            stringRedisTemplate.opsForValue().set(redisKey, v_code, 60, TimeUnit.SECONDS);
        }

    }


    @Override
    public AppBlindAuthLoginRespVO wechatAppLogin(AppWechatLoginReqVo reqVO) {
        //todo 确定state 前台传过来的是什么
        AuthUser authUser = getAuthUser(WECHAT_MINI_APP.getType(), reqVO.getLoginCode(), UUID.randomUUID().toString());
        Assert.notNull(authUser, "三方用户不能为空");
        String openId = authUser.getUuid();
        BlindMemberUserDO blindMemberUserDO = this.selectByWxOpenId(openId);
        if (Objects.isNull(blindMemberUserDO)) {
            BlindMemberUserCreateReqVO createReqVO = new BlindMemberUserCreateReqVO();
            createReqVO.setWxOpenId(openId);
            addUserNo(createReqVO);
            createReqVO.setRegisterIp(getClientIP());
            Long userId = this.createMemberUser(createReqVO);
            OAuth2AccessTokenRespDTO accessTokenRespDTO = oauth2TokenApi.createAccessToken(new OAuth2AccessTokenCreateReqDTO()
                    .setUserId(userId).setUserType(UserTypeEnum.MEMBER.getValue())
                    .setClientId(OAuth2ClientConstants.CLIENT_ID_DEFAULT));
            return BlindAuthConvert.INSTANCE.convert(accessTokenRespDTO);
        }

        OAuth2AccessTokenRespDTO accessTokenRespDTO = oauth2TokenApi.createAccessToken(new OAuth2AccessTokenCreateReqDTO()
                .setUserId(blindMemberUserDO.getId()).setUserType(UserTypeEnum.MEMBER.getValue())
                .setClientId(OAuth2ClientConstants.CLIENT_ID_DEFAULT));
        return BlindAuthConvert.INSTANCE.convert(accessTokenRespDTO);
    }


    @Override
    public void appWechatBindPhone(Long userId, AppWechatBindReqVo appWechatBindReqVo) {
        BlindMemberUserUpdateReqVO updateReqVO = new BlindMemberUserUpdateReqVO();
        updateReqVO.setId(userId);
        updateReqVO.setMobile(appWechatBindReqVo.getMobile());
        this.updateMemberUser(updateReqVO);
    }

    @Override
    public PageResult<BlindMemberUserDO> searchBlindMembers(AppBlindUserPageReqVO pageVO) {
        return blindMemberUserMapper.searchMemberPage(pageVO);
    }

    private AppBlindAuthLoginRespVO buildAppBlindAuthLoginRespVO(MemberPrivilegeDO memberPrivilegeDO, AppBlindAuthLoginRespVO appBlindAuthLoginRespVO) {
        if (Objects.equals(memberPrivilegeDO.getPrivilegeName(), "尊贵标识")) {
            appBlindAuthLoginRespVO.setNobleLogo(memberPrivilegeDO.getStatus());
        } else if (Objects.equals(memberPrivilegeDO.getPrivilegeName(), "专属客服")) {
            appBlindAuthLoginRespVO.setExclusiveCustomer(memberPrivilegeDO.getStatus());
        } else if (Objects.equals(memberPrivilegeDO.getPrivilegeName(), "高级搜索")) {
            appBlindAuthLoginRespVO.setAdvancedSearch(memberPrivilegeDO.getStatus());
        } else if (Objects.equals(memberPrivilegeDO.getPrivilegeName(), "谁向我打招呼")) {
            appBlindAuthLoginRespVO.setWhoSayHello(memberPrivilegeDO.getStatus());
        } else if (Objects.equals(memberPrivilegeDO.getPrivilegeName(), "谁喜欢我")) {
            appBlindAuthLoginRespVO.setWhoLike(memberPrivilegeDO.getStatus());
        } else if (Objects.equals(memberPrivilegeDO.getPrivilegeName(), "谁看过我")) {
            appBlindAuthLoginRespVO.setWhoSeeMe(memberPrivilegeDO.getStatus());
        } else if (Objects.equals(memberPrivilegeDO.getPrivilegeName(), "发布活动")) {
            appBlindAuthLoginRespVO.setReleaseActivity(memberPrivilegeDO.getStatus());
        } else if (Objects.equals(memberPrivilegeDO.getPrivilegeName(), "强制配对")) {
            appBlindAuthLoginRespVO.setForceMatching(memberPrivilegeDO.getStatus());
        } else if (Objects.equals(memberPrivilegeDO.getPrivilegeName(), "打招呼")) {
            appBlindAuthLoginRespVO.setSayHello(memberPrivilegeDO.getStatus());
        } else if (Objects.equals(memberPrivilegeDO.getPrivilegeName(), "喜欢")) {
            appBlindAuthLoginRespVO.setLike(memberPrivilegeDO.getStatus());
        }
        return appBlindAuthLoginRespVO;
    }

    /**
     * 随机页缓存key
     */
    private final static String BASIC_MATCH_BLIND_MEMBER = "basic_match_blind_member:";
    //    ①注册进来后在未填写择偶条件下，系统推荐规则根据：异性、有头像、年龄差距上下在10岁的、登录时填写的所在地区去推荐。
    //    ②填写择偶条件后，根据后台设定的匹配度去随机推荐满足的人
    @Override
    public List<BlindMemberUserDO> basicMatchBlindMembers(Integer matchDegree, Long loginUserId,BlindMemberUserDO memberUser) {

        //获取随机页数 将所有数据写到缓存中 下次随机到这个数值 直接从缓存中查
        Random ran = new Random();
        int i = Integer.parseInt(maxRandom);
        int ranNum = ran.nextInt(i);
        String basicBlindUser = stringRedisTemplate.opsForValue().get(BASIC_MATCH_BLIND_MEMBER + loginUserId + ":" + ranNum);
        if (StringUtils.isNotEmpty(basicBlindUser)){
            return JSON.parseArray(basicBlindUser,BlindMemberUserDO.class);
        }

        List<BlindMemberUserDO> memberUserDOS = new ArrayList<>();

        //匹配超级推荐数据
        getRecommendList(memberUser, loginUserId, memberUserDOS);
        //插入喜欢我的数据
        getLikeList(loginUserId,memberUserDOS);

        Integer memberUserNum = blindMemberUserMapper.getMemberUserNum();
        AppBlindUserPageReqVO appBlindUserPageReqVO = buildPageReq(memberUser, loginUserId);
        if (memberUserNum >= 500) {
            // 获取当前时间戳（毫秒）
            long timestamp = System.currentTimeMillis();
            // 转换为秒，并获取其字符串表示
            String timestampStr = Long.toString(timestamp / 1000);
            // 获取最后一位
            char lastDigit = timestampStr.charAt(timestampStr.length() - 1);
            appBlindUserPageReqVO.setMobile(String.valueOf(lastDigit));
        }
        Long l = blindMemberUserMapper.selectBasicCount(appBlindUserPageReqVO);
        //根据总数随机给他返回一个页码
        int randomPage = generateRandomPageNumber(Integer.parseInt(String.valueOf(l)), Integer.parseInt(basicPageSize));
        appBlindUserPageReqVO.setPageNo(randomPage);
        appBlindUserPageReqVO.setPageSize(Integer.parseInt(basicPageSize));
        //随机获取的配置的条数数据
        PageResult<BlindMemberUserDO> blindMemberUserDOPageResult = null;
        blindMemberUserDOPageResult = blindMemberUserMapper.selectBasicList(appBlindUserPageReqVO);
        if (Objects.nonNull(blindMemberUserDOPageResult)){
            List<BlindMemberUserDO> list = blindMemberUserDOPageResult.getList();
            if (CollectionUtils.isNotEmpty(list)){
               Collections.shuffle(list);
               memberUserDOS.addAll(list);
            }
        }
        //去重
        List<BlindMemberUserDO> blindMemberUserDOS = memberUserDOS.stream().distinct().collect(Collectors.toList());
        stringRedisTemplate.opsForValue().set(BASIC_MATCH_BLIND_MEMBER + loginUserId + ":" + ranNum, JSON.toJSONString(blindMemberUserDOS),12, TimeUnit.HOURS);
        return blindMemberUserDOS;
    }

    public static int generateRandomPageNumber(int totalItems, int itemsPerPage) {
        if (totalItems <= 0 || itemsPerPage <= 0) {
            return 1;
        }
        int totalPages = (int) Math.ceil((double) totalItems / itemsPerPage);
        Random random = new Random();
        return random.nextInt(totalPages) + 1;
    }



    private AppBlindUserPageReqVO buildPageReq(BlindMemberUserDO memberUser, Long loginUserId) {
        //女下3上8 男下8上3
        AppBlindUserPageReqVO pageVO = new AppBlindUserPageReqVO();
        if (Objects.equals(memberUser.getSex(), (byte) 1)) {
            pageVO.setAgeMix(memberUser.getAge() - 3);
            pageVO.setAgeMax(memberUser.getAge() + 8);
            pageVO.setSex((byte) 2);
        } else if (Objects.equals(memberUser.getSex(), (byte) 2)) {
            pageVO.setAgeMix(memberUser.getAge() - 8);
            pageVO.setAgeMax(memberUser.getAge() + 3);
            pageVO.setSex((byte) 1);
        }
        pageVO.setId(loginUserId);
        return pageVO;
    }

    @Override
    public BlindMemberUserDO selectByNickName(String nickName) {
        return blindMemberUserMapper.selectOne(BlindMemberUserDO::getNickname, nickName);
    }


    /**
     * 构建择偶条件
     *
     * @param memberUser
     * @return
     */
    private AppBlindUserPageReqVO writeSingle(AppBlindUserPageReqVO pageVO, BlindMemberUserDO memberUser, Integer num) {
        pageVO = new AppBlindUserPageReqVO();
        pageVO.setSex(memberUser.getSex());
        Integer process = 0;
        if (num == 0) {
            return pageVO;
        }
        if (StringUtils.isNotEmpty(memberUser.getMatchAge())) {
            List<String> ageList = MemberUserEnumUtil.matchAge(DictFrameworkUtils.getDictDataLabel(
                    BlindDictTypeConstants.MATCH_AGE, memberUser.getMatchAge()));
            if (CollectionUtils.isNotEmpty(ageList)) {
                pageVO.setAgeMix(Integer.parseInt(ageList.get(0)));
                pageVO.setAgeMax(Integer.parseInt(ageList.get(1)));
            }
            process++;
            if (Objects.equals(num, process)) {
                return pageVO;
            }
        }
        if (StringUtils.isNotEmpty(memberUser.getMatchHeight())) {
            List<String> heightList = MemberUserEnumUtil.matchHeight(DictFrameworkUtils.getDictDataLabel(BlindDictTypeConstants.MATCH_HEIGHT, memberUser.getMatchHeight()));
            if (CollectionUtils.isNotEmpty(heightList)) {
                pageVO.setHeightMix(heightList.get(0));
                pageVO.setHeightMax(heightList.get(1));
            }
            process++;
            if (Objects.equals(num, process)) {
                return pageVO;
            }
        }

        if (StringUtils.isNotEmpty(memberUser.getMatchIncome())) {
            pageVO.setMonthIncome(memberUser.getMatchIncome());
            process++;
            if (Objects.equals(num, process)) {
                return pageVO;
            }
        }

        if (StringUtils.isNotEmpty(memberUser.getMatchEducation())) {
            pageVO.setEducation(memberUser.getMatchEducation());
            process++;
            if (Objects.equals(num, process)) {
                return pageVO;
            }

        }

        if (StringUtils.isNotEmpty(memberUser.getMatchMarriage())) {
            pageVO.setMarriage(memberUser.getMatchMarriage());
            process++;
            if (Objects.equals(num, process)) {
                return pageVO;
            }

        }

        if (StringUtils.isNotEmpty(memberUser.getMatchWorkArea())) {
            pageVO.setAreaId(memberUser.getMatchWorkArea());
            process++;
            if (Objects.equals(num, process)) {
                return pageVO;
            }

        }

        if (Objects.nonNull(memberUser.getMatchWithChild())) {
            pageVO.setWithChild(memberUser.getMatchWithChild());
            process++;
            if (Objects.equals(num, process)) {
                return pageVO;
            }
        }

        if (Objects.nonNull(memberUser.getMatchWantChild())) {
            pageVO.setWantChild(memberUser.getMatchWantChild());
            process++;
            if (Objects.equals(num, process)) {
                return pageVO;
            }

        }

        if (Objects.nonNull(memberUser.getMatchSmoker())) {
            pageVO.setSmoker(memberUser.getMatchSmoker());
            process++;
            if (Objects.equals(num, process)) {
                return pageVO;
            }

        }

        if (Objects.nonNull(memberUser.getMatchDrink())) {
            pageVO.setDrink(memberUser.getMatchDrink());
            process++;
            if (Objects.equals(num, process)) {
                return pageVO;
            }
        }
        return pageVO;
    }


    private AppBlindUserPageReqVO writeConditions(AppBlindUserPageReqVO pageVO, BlindMemberUserDO memberUser) {
        pageVO.setSex(memberUser.getSex());
        if (Objects.nonNull(memberUser.getAge())) {
            List<String> ageList = MemberUserEnumUtil.matchAge(DictFrameworkUtils.getDictDataLabel(
                    BlindDictTypeConstants.MATCH_AGE, memberUser.getAge()));
            if (CollectionUtils.isNotEmpty(ageList)) {
                pageVO.setAgeMix(Integer.parseInt(ageList.get(0)));
                pageVO.setAgeMax(Integer.parseInt(ageList.get(1)));
            }
        }
        if (StringUtils.isNotEmpty(memberUser.getHeight())) {
            List<String> heightList = MemberUserEnumUtil.matchHeight(DictFrameworkUtils.getDictDataLabel(BlindDictTypeConstants.MATCH_HEIGHT, memberUser.getHeight()));
            if (CollectionUtils.isNotEmpty(heightList)) {
                pageVO.setHeightMix(heightList.get(0));
                pageVO.setHeightMax(heightList.get(1));
            }
        }
        return pageVO;
    }

    private void getRecommendList(BlindMemberUserDO memberUser, Long loginUserId, List<BlindMemberUserDO> memberUserDOS) {
        AppBlindUserPageReqVO pageVO = new AppBlindUserPageReqVO();
        if (Objects.equals(memberUser.getHaveRecommend(), (byte) 1)) {
            if (memberUser.getRecommendEnd() != null && memberUser.getRecommendEnd().isAfter(LocalDateTime.now())) {
                AppBlindUserPageReqVO blindUserPageReqVO = writeConditions(pageVO, memberUser).setId(loginUserId);
                Long l = blindMemberUserMapper.selectMyConditionsCount(blindUserPageReqVO);
                //根据总数随机给他返回一个页码

                int randomPage = generateRandomPageNumber(Integer.parseInt(String.valueOf(l)), Integer.parseInt(likePageSize));
                blindUserPageReqVO.setPageNo(randomPage);
                blindUserPageReqVO.setPageSize(Integer.parseInt(likePageSize));
                PageResult<BlindMemberUserDO> blindMemberUserDOPageResult = blindMemberUserMapper.selectMyConditionsList(blindUserPageReqVO);
                if (Objects.nonNull(blindMemberUserDOPageResult)){
                    if (CollectionUtils.isNotEmpty(memberUserDOS)) {
                        List<BlindMemberUserDO> blindMemberUserDOS = blindMemberUserDOPageResult.getList();
                        blindMemberUserDOS = blindMemberUserDOS.stream().sorted(Comparator
                                        .comparing(BlindMemberUserDO::getRecommendBegin, Comparator
                                                .nullsFirst(Comparator.naturalOrder())))
                                .collect(Collectors.toList());
                        Collections.shuffle(blindMemberUserDOS);
                        memberUserDOS.addAll(blindMemberUserDOS);
                    }
                }
            }
        }
    }

    private void getLikeList(Long loginUserId,List<BlindMemberUserDO> memberUserDOS){
        MemberLikePageReqVO pageReqVO  = new MemberLikePageReqVO();
        pageReqVO.setReceive(String.valueOf(loginUserId));
        Long memberLikeCount = memberLikeService.getMemberLikeCount(pageReqVO);
        int randomPage = generateRandomPageNumber(Integer.parseInt(String.valueOf(memberLikeCount)), Integer.parseInt(likePageSize));
        pageReqVO.setPageNo(randomPage);
        pageReqVO.setPageSize(Integer.parseInt(likePageSize));
        PageResult<MemberLikeDO> memberLikePage = memberLikeService.getMemberLikePage(pageReqVO);
        if (Objects.nonNull(memberLikePage)) {
            List<MemberLikeDO> memberLikeList = memberLikePage.getList();
            if (CollectionUtils.isNotEmpty(memberLikeList)){
                List<String> collect = memberLikeList.stream().map(MemberLikeDO::getIssue).collect(Collectors.toList());
                List<Long> userIdList = collect.stream()
                        .map(Long::parseLong)
                        .collect(Collectors.toList());
                List<BlindMemberUserDO> blindMemberUserDOS = blindMemberUserMapper.selectBatchIds(userIdList);
                if (CollectionUtils.isNotEmpty(blindMemberUserDOS)) {
                    Collections.shuffle(blindMemberUserDOS);
                    memberUserDOS.addAll(blindMemberUserDOS);
                }
            }
        }
    }

    /**
     * 填写了几个择偶条件
     *
     * @param memberUser
     * @return
     */
    private Integer haveImSingle(BlindMemberUserDO memberUser) {
        Integer single = 0;
        if (StringUtils.isNotEmpty(memberUser.getMatchIncome()) && !Objects.equals(memberUser.getMatchIncome(), "0"))
            single++;
        if (StringUtils.isNotEmpty(memberUser.getMatchAge()) && !Objects.equals(memberUser.getMatchAge(), "0"))
            single++;
        if (StringUtils.isNotEmpty(memberUser.getMatchHeight()) && !Objects.equals(memberUser.getMatchHeight(), "0"))
            single++;
        if (Objects.nonNull(memberUser.getMatchDrink()) && !Objects.equals(memberUser.getMatchDrink(), (byte) 0))
            single++;
        if (StringUtils.isNotEmpty(memberUser.getMatchEducation()) && !Objects.equals(memberUser.getMatchEducation(), "0"))
            single++;
        if (Objects.nonNull(memberUser.getMatchSmoker()) && !Objects.equals(memberUser.getMatchEducation(), "0"))
            single++;
        if (Objects.nonNull(memberUser.getMatchWantChild()) && !Objects.equals(memberUser.getMatchWantChild(), (byte) 0))
            single++;
        if (Objects.nonNull(memberUser.getMatchWithChild()) && !Objects.equals(memberUser.getMatchWithChild(), (byte) 0))
            single++;
        if (StringUtils.isNotEmpty(memberUser.getMatchWorkArea()) && !Objects.equals(memberUser.getMatchWorkArea(), "0"))
            single++;
        if (StringUtils.isNotEmpty(memberUser.getMatchMarriage()) && !Objects.equals(memberUser.getMatchMarriage(), "0"))
            single++;
        return single;
    }


    /**
     * 请求社交平台，获得授权的用户
     *
     * @param type  社交平台的类型
     * @param code  授权码
     * @param state 授权 state
     * @return 授权的用户
     */
    private AuthUser getAuthUser(Integer type, String code, String state) {
        AuthRequest authRequest = yudaoAuthRequestFactory.get(SocialTypeEnum.valueOfType(type).getSource());
        AuthCallback authCallback = AuthCallback.builder().code(code).state(state).build();
        AuthResponse<?> authResponse = authRequest.login(authCallback);
        if (!authResponse.ok()) {
            throw exception(SOCIAL_USER_AUTH_FAILURE, authResponse.getMsg());
        }
        return (AuthUser) authResponse.getData();
    }


    @Override
    public AdminUserDO authenticate(String username, String password) {
        final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_USERNAME;
        // 校验账号是否存在
        AdminUserDO user = userService.getUserByUsername(username);
        if (user == null) {
            createLoginLog(null, username, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
            throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
        }
        if (!userService.isPasswordMatch(password, user.getPassword())) {
            createLoginLog(user.getId(), username, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS);
            throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
        }
        // 校验是否禁用
        if (ObjectUtil.notEqual(user.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
            createLoginLog(user.getId(), username, logTypeEnum, LoginResultEnum.USER_DISABLED);
            throw exception(AUTH_LOGIN_USER_DISABLED);
        }
        return user;
    }


    private void createLoginLog(Long userId, String username,
                                LoginLogTypeEnum logTypeEnum, LoginResultEnum loginResult) {
        // 插入登录日志
        LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO();
        reqDTO.setLogType(logTypeEnum.getType());
        reqDTO.setTraceId(TracerUtils.getTraceId());
        reqDTO.setUserId(userId);
        reqDTO.setUserType(getUserType().getValue());
        reqDTO.setUsername(username);
        reqDTO.setUserAgent(ServletUtils.getUserAgent());
        reqDTO.setUserIp(ServletUtils.getClientIP());
        reqDTO.setResult(loginResult.getResult());
        loginLogService.createLoginLog(reqDTO);
        // 更新最后登录时间
        if (userId != null && Objects.equals(LoginResultEnum.SUCCESS.getResult(), loginResult.getResult())) {
            userService.updateUserLogin(userId, ServletUtils.getClientIP());
        }
    }

    private AuthLoginRespVO createTokenAfterLoginSuccess(Long userId, String username, LoginLogTypeEnum logType) {
        // 插入登陆日志
        createLoginLog(userId, username, logType, LoginResultEnum.SUCCESS);
        // 创建访问令牌
        OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(userId, getUserType().getValue(),
                OAuth2ClientConstants.CLIENT_ID_DEFAULT, null);
        // 构建返回结果
        return AuthConvert.INSTANCE.convert(accessTokenDO);
    }

    private UserTypeEnum getUserType() {
        return UserTypeEnum.MERCHANT;
    }


    @Override
    public List<AppTeamReqVo> getTeamList(Long userId) {
        List<AppTeamReqVo> list = blindMemberUserMapper.getTeamList(String.valueOf(userId));
        return list;
    }

    @Override
    public DistributionVo getDistributionInfo(Long id) {
        DistributionVo vo = new DistributionVo();
        BlindMemberUserDO userDO = blindMemberUserMapper.selectById(id);
        BlindMemberUserRespVO blindMemberUserRespVO = BlindMemberUserConvert.INSTANCE.convert(userDO);
        BeanUtil.copyProperties(blindMemberUserRespVO, vo);
        vo.setId(userDO.getId());
        vo.setTeam(blindMemberUserMapper.getTeam(String.valueOf(id)));
        vo.setPerformance(blindMemberUserMapper.getPerformance(String.valueOf(id)));
        return vo;
    }

    @Override
    public void updateUserMobile(Long userId, AppBlindUserUpdateMobileReqVO reqVO) {
        // 检测用户是否存在
        BlindMemberUserDO user = validateUserExists(userId);
        // 校验新手机是否已经被绑定
        validateMobileUnique(null, reqVO.getMobile());

        String redisKey = memberSmsSendKey + reqVO.getMobile();
        String code = stringRedisTemplate.opsForValue().get(redisKey);
        //校验验证码
        Assert.notNull(Objects.equals(reqVO.getCode(), code), "获取验证码失败");

        // 更新用户手机
        blindMemberUserMapper.updateById(BlindMemberUserDO.builder().id(userId).mobile(reqVO.getMobile()).build());
    }

    @VisibleForTesting
    BlindMemberUserDO validateUserExists(Long id) {
        if (id == null) {
            return null;
        }
        BlindMemberUserDO user = blindMemberUserMapper.selectById(id);
        if (user == null) {
            throw exception(USER_NOT_EXISTS);
        }
        return user;
    }

    @VisibleForTesting
    void validateMobileUnique(Long id, String mobile) {
        if (StrUtil.isBlank(mobile)) {
            return;
        }
        BlindMemberUserDO user = selectByMobile(mobile);
        if (user == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的用户
        if (id == null) {
            throw exception(USER_MOBILE_USED, mobile);
        }
        if (!user.getId().equals(id)) {
            throw exception(USER_MOBILE_USED, mobile);
        }
    }

    /**
     * 需要满足几个条件
     *
     * @param single
     * @param matchDegree
     */
    private Integer matchConditions(Integer single, Integer matchDegree) {
        Integer matchNum = matchDegree / 10;
        //不限的值 (10 - single)
        int i = 10 - single;
        if (i > matchNum) {
            return 0;
        } else {
            return matchNum - i;
        }
    }

    @Override
    public int getMerchantNum(String name) {
        return blindMemberUserMapper.getMerchantNum(name);
    }


    public void updateIdNumberAuth(MemberUserAuthVO authVO) {
        blindMemberUserMapper.update(null, new LambdaUpdateWrapper<BlindMemberUserDO>()
                .set(BlindMemberUserDO::getSex, authVO.getSex())
                .set(authVO.getAge() != null, BlindMemberUserDO::getAge, authVO.getAge())
                .set(StringUtils.isNotEmpty(authVO.getConstellation()), BlindMemberUserDO::getConstellation, authVO.getConstellation())
                .set(StringUtils.isNotEmpty(authVO.getBirthday()), BlindMemberUserDO::getBirthday, authVO.getBirthday())
                .eq(BlindMemberUserDO::getId, authVO.getId()));

    }

    public void updateAvatarAuth(MemberUserAuthVO authVO) {
        blindMemberUserMapper.update(null, new LambdaUpdateWrapper<BlindMemberUserDO>()
                .set(BlindMemberUserDO::getAvatarAuth, authVO.getAvatarAuth())
                .eq(BlindMemberUserDO::getId, authVO.getId()));

    }

    /**
     * 修改内心的独白
     */
    public void updateContent(Long id, String content) {
        blindMemberUserMapper.update(null, new LambdaUpdateWrapper<BlindMemberUserDO>()
                .set(BlindMemberUserDO::getInnerMonologue, content)
                .eq(BlindMemberUserDO::getId, id));

    }

    @Override
    public int getUserCount(String name) {
        return blindMemberUserMapper.getUserCount(name);
    }


}
